package com.jkoss.wine.shiro;

import java.util.ArrayList;
import java.util.List;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.Condition;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.jkoss.common.util.CommonUtil;
import com.jkoss.common.util.Constant;
import com.jkoss.wine.system.entity.MerchantEmployees;
import com.jkoss.wine.system.entity.Permission;
import com.jkoss.wine.system.service.IMerchantEmployeesService;
import com.jkoss.wine.system.service.IPermissionService;

/**
 * 自定义realm
 * 
 * @author Jason
 *
 */
public class AuthRealm extends AuthorizingRealm {

	@Autowired
	private IMerchantEmployeesService iMerchantEmployeesService;
	@Autowired
	private IPermissionService iPermissionService;

	private Logger log = LoggerFactory.getLogger(getClass());

	// 执行认证逻辑
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
		log.debug("[认证]	登录等操作");
		// shiro判断逻辑
		// 获取用户名密码
		UsernamePasswordToken user = (UsernamePasswordToken) arg0;
		// 登录逻辑
		// 用户名
		String name = user.getUsername();
		// 密码
		char[] pwd = user.getPassword();
		Wrapper wrapper = Condition.create().eq("account_num", name).eq("employee_state", 0).ne("del", 1);
		MerchantEmployees merchantEmployees = iMerchantEmployeesService.selectOne(wrapper);
		if (CommonUtil.isBlank(merchantEmployees)) {
			throw new UnknownAccountException();
		}
		if (!CommonUtil.isEquals(merchantEmployees.getAccountPwd(), new String(pwd))) {
			throw new IncorrectCredentialsException();
		}

		// shiro是不涉及系统的权限的维护的，权限的维护全都是系统自己维护的，自己设计的
		// 需要自己查询用户的所有权限,包括显示菜单，功能菜单，按钮
		List<Permission> list = iPermissionService.selectByMeid(merchantEmployees.getEmployeeId());
		List list2 = new ArrayList();
		// 菜单信息
		List menus = new ArrayList();
		for (Permission permission : list) {
			// 递归
			if (CommonUtil.isBlank(permission.getPid())) {
				submenu(permission, list);
				menus.add(permission);
			}

			if (!CommonUtil.isBlank(permission.getUrl())) {
				list2.add(permission.getUrl());
			}
		}

		// 登录成功 把用户保存到session
		SecurityUtils.getSubject().getSession(true).setAttribute(Constant.SESSION_USER_KEY, merchantEmployees);
		SecurityUtils.getSubject().getSession(true).setAttribute(Constant.SESSION_URLS_KEY, list2);

		SecurityUtils.getSubject().getSession(true).setAttribute(Constant.SESSION_MENU_KEY, JSON.toJSONString(menus));
		return new SimpleAuthenticationInfo(merchantEmployees, merchantEmployees.getAccountPwd(),
				merchantEmployees.getEmployeeName());
	}

	// 执行授权
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
		log.debug("[授权]	权限验证");
		// 授权
		// 给资源授权

		SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
		// 接收的字符串数组
		List list2 = (List) SecurityUtils.getSubject().getSession(true).getAttribute(Constant.SESSION_URLS_KEY);
		simpleAuthorizationInfo.addStringPermissions(list2);
		return simpleAuthorizationInfo;
	}

	/**
	 * 无限级菜单：使用递归算法
	 *
	 * @param permission	第一级菜单
	 * @param permissions	所用的菜单
	 * @return
	 */
	private void submenu(Permission permission, List<Permission> permissions) {
		for (Permission permission2 : permissions) {
			if (CommonUtil.isEquals(permission.getId().toString(), permission2.getPid())) {
				List list = permission.getSubmenu();
				if (CommonUtil.isBlank(list)) {
					list = new ArrayList();
				}
				list.add(permission2);
				permission.setSubmenu(list);
				submenu(permission2, permissions);
			}
		}
	}
}
